from tkinter import *
import tkinter.filedialog   #文件选择
import tkinter.messagebox  #提示框
import cv2
from PIL import Image,ImageTk
import numpy as np
from numpy import fft
import math
import random
class MyGUI(object):
    def __init__(self):
        self.tk=Tk()
        # 创建文本框，用于显示程序运行结果。
        self.text = Entry(self.tk,bd = 4,relief=GROOVE,borderwidth=3, width=45, font=('Helvetica', '18', 'normal'))
        self.B = Button(self.tk, text='清空', command=self.clear_text)  # 清空按钮
        self.B_get = Button(self.tk, text='获取', command=self.aquire_text)  # 获取按钮
        self.menubar = Menu(self.tk) #菜单
        self.canvas1 = Canvas(self.tk,bd= 0, width=360, height=350,bg = 'black',relief = RAISED)  # 创建画布1
        self.canvas2 = Canvas(self.tk, bd = 0,width=360, height=350,bg = 'black',relief = RAISED)  # 创建画布2
        self.lb = Label(self.tk, text='')  #用于显示图片路径
        self.lb.pack()

    def __call__(self, *args, **kwargs):
        self.tk.title('数字图像处理')  # 标题
        self.tk.geometry('950x500')  # 窗口大小
        self.text.pack(side=TOP)
        self.B.pack() #清除按钮放置
        self.B_get.pack() #获取按钮
        self.init_menu()  #调用构造具体菜单内容的函数
        self.canvas1.pack(side = LEFT)  # 显示画布
        self.canvas2.pack(side = RIGHT)  # 显示画布
        self.tk.mainloop()
    def aquire_text(self):   #获取文本框中的内容
        if not hasattr(self, 'value'):   #判断是否有img这个属性
            setattr(self, 'value','')   #设置属性
        self.value = self.text.get()  #获取内容的值,类型是str
        return self.value
    def Out_photo(self,img):
        if not hasattr(self, 'img2'):  # 判断是否有img这个属性
            setattr(self, 'img2', '')
        self.img2 = img
        if not hasattr(self, 'imgtk2'):  # 判断是否有img这个属性
            setattr(self, 'imgtk2', '')  # 设置属性
        self.imgtk2 = self.photo_chage_2()
        self.canvas2.create_image(0, 0, anchor="nw", image=self.imgtk2)
    def init_menu(self):
        tk = self.tk
        menu_main = self.menubar
        menu_1 = Menu(tk)
        j = 1
        for i in ['打开','调用摄像头','rgb2gray','BGR转二值','BGR转YCbCr','保存','退出']:
            fun_name = 'do_job1_' + str(j)
            menu_1.add_command(label = i,command = getattr(self,fun_name,None))  #getattr实现字符串调用类方法
            j += 1
        menu_2 = Menu(tk)
        j = 1
        for i in ['点运算', '代数运算', '逻辑运算', '分析连通', '计算距离']:
            fun_name = 'do_job2_' + str(j)
            menu_2.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        j = 1
        menu_3 = Menu(tk)
        for i in ['移动', '旋转','垂直镜像','水平镜像','缩放','仿射变换','透视变换','最近邻插法','双线性插值','三次内插法']:
            fun_name = 'do_job3_' + str(j)
            menu_3.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        j = 1
        menu_4 = Menu(tk)
        for i in ['直方图', '掩模直方图', '局部直方图', '直方图均衡化', '直方图规定化']:
            fun_name = 'do_job4_' + str(j)
            menu_4.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        j = 1
        menu_5 = Menu(tk)
        for i in [ '模板1', '模板2', '模板3','高斯滤波','中值波波','最大滤波','最小滤波','Pad the image','Replicate border pixels','Mirror-reflecting at borders',' Allow pixels wrap around the image','梯度锐化','sobel锐化','LOG锐化','拉普拉斯锐化','canny锐化']:
            fun_name = 'do_job5_' + str(j)
            menu_5.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        j = 1
        menu_6 = Menu(tk)
        for i in ['傅里叶正变换', '傅里叶反变换', '低通滤波器', '高通滤波器']:
            fun_name = 'do_job6_' + str(j)
            menu_6.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        j = 1
        menu_7 = Menu(tk)
        for i in ['椒盐噪声', '均值滤波器', '顺序统计滤波器']:
            fun_name = 'do_job7_' + str(j)
            menu_7.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        j = 1
        menu_8 = Menu(tk)
        for i in [ '带通滤波器','带阻滤波器','加周期噪声','陷波带阻滤波器']:
            fun_name = 'do_job8_' + str(j)
            menu_8.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        menu_9 = Menu(tk)
        j = 1
        for i in ['高斯模糊', '运动模糊','大气湍流模糊', '逆滤波', '改进逆滤波','维纳滤波',' 最小二乘滤波']:
            fun_name = 'do_job9_' + str(j)
            menu_9.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        menu_10 = Menu(tk)
        j = 1
        for i in ['膨胀', '腐蚀', '边界提取','开运算', '闭运算', '连通分量提取']:
            fun_name = 'do_job10_' + str(j)
            menu_10.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        j = 1
        menu_11 = Menu(tk)
        for i in ['获取图像轮廓并二值化处理', '轮廓连接方法', 'Hough变换进行直线检测']:
            fun_name = 'do_job11_' + str(j)
            menu_11.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        j = 1
        menu_12 = Menu(tk)
        for i in [' Global Thresholding', 'OTSU', '局部可变阈值']:
            fun_name = 'do_job12_' + str(j)
            menu_12.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        j = 1
        menu_13 = Menu(tk)
        for i in ['算术平均法去噪', '空域平滑去噪', '频域低通去噪', '形态学滤波去噪']:
            fun_name = 'do_job13_' + str(j)
            menu_13.add_command(label=i, command=getattr(self, fun_name, None))  # getattr实现字符串调用类方法
            j += 1
        menu_main.add_cascade(label="文件", menu=menu_1)
        menu_main.add_cascade(label="基本运算", menu=menu_2)
        menu_main.add_cascade(label="几何运算", menu=menu_3)
        menu_main.add_cascade(label="直方图修正方法", menu=menu_4)
        menu_main.add_cascade(label="空间滤波增强", menu=menu_5)
        menu_main.add_cascade(label="频域图像增强", menu=menu_6)
        menu_main.add_cascade(label="空域复原", menu=menu_7)
        menu_main.add_cascade(label="频域复原", menu=menu_8)
        menu_main.add_cascade(label="退化函数及其复原", menu=menu_9)
        menu_main.add_cascade(label="形态学运算", menu=menu_10)
        menu_main.add_cascade(label="边缘连接", menu=menu_11)
        menu_main.add_cascade(label="阈值分割", menu=menu_12)
        menu_main.add_cascade(label="去噪", menu=menu_13)
        # 最后可以用窗口的 menu 属性指定我们使用哪一个作为它的顶层菜单
        tk.config(menu=menu_main)

    #清除
    def clear_text(self):
        self.text.delete(0, END)
    # -------功能实现接口----------
    #第一个菜单接口----------------------------------------------------------
    # 打开文件中的图片
    def do_job1_1(self):
        filename = tkinter.filedialog.askopenfilename()
        if filename != '':
            self.lb.config(text="您选择的文件是：" + filename)
        else:
            self.lb.config(text="您没有选择任何文件")
        if not hasattr(self, 'img1_Ima'):  # 判断是否有img这个属性
            setattr(self, 'img1_Ima', '')  # 设置属性
        if not hasattr(self, 'img1'):  # 判断是否有img这个属性
            setattr(self, 'img1', '')  # 设置属性
        self.img1 = cv2.imread(filename,0)
        self.img1 = cv2.resize(self.img1,(360, 350))
        self.get_attr()
        self.img1_Ima = Image.open(filename).resize((360, 350))
        # print(filename)
        if not hasattr(self, 'imgtk1'):  # 判断是否有img这个属性
            setattr(self, 'imgtk1', '')  # 设置属性
        # self.get_attr()
        self.imgtk1 = self.photo_chage()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
    #调用摄像头
    def do_job1_2(self):
        cv2.namedWindow("Image")  # 创建窗口
        cap = cv2.VideoCapture(0)  # 利用内置摄像头捕获视频
        self.video_loop(cap)
        cap.release()   #释放摄像头
        cv2.destroyAllWindows()   #关闭窗口
    # RGB转换为gray
    def do_job1_3(self):
        temp = self.img1_Ima
        gray = self.img1_Ima.convert("L")  # RGB转换为gray
        self.img1_Ima = temp
        if not hasattr(self, 'img2_Ima'):   #判断是否有img这个属性
            setattr(self,'img2_Ima','')
        self.img2_Ima = gray
        if not hasattr(self, 'imgtk2'):   #判断是否有img这个属性
            setattr(self, 'imgtk2','')   #设置属性
        self.imgtk2 = self.photo_chage_1()
        self.canvas2.create_image(0, 0, anchor="nw", image=self.imgtk2)
        # BGR转换为gray
    #BGR转bianry
    def do_job1_4(self):
        temp = self.img1_Ima
        binary = self.img1_Ima.convert("1")  # RGB转换为gray
        self.img1_Ima = temp
        if not hasattr(self, 'img2_Ima'):   #判断是否有img这个属性
            setattr(self,'img2_Ima','')
        self.img2_Ima = binary
        if not hasattr(self, 'imgtk2'):   #判断是否有img这个属性
            setattr(self, 'imgtk2','')   #设置属性
        self.imgtk2 = self.photo_chage_1()
        self.canvas2.create_image(0, 0, anchor="nw", image=self.imgtk2)
    #BGR转YCbCr
    def do_job1_5(self):
        temp = self.img1_Ima
        YCbCr = self.img1_Ima.convert("YCbCr")  # RGB转换为gray
        self.img1_Ima = temp
        if not hasattr(self, 'img2_Ima'):   #判断是否有img这个属性
            setattr(self,'img2_Ima','')
        self.img2_Ima = YCbCr
        if not hasattr(self, 'imgtk2'):   #判断是否有img这个属性
            setattr(self, 'imgtk2','')   #设置属性
        self.imgtk2 = self.photo_chage_1()
        self.canvas2.create_image(0, 0, anchor="nw", image=self.imgtk2)
    # #RGB转换为HSV
    # def do_job1_4(self):
    #     temp = self.img1
    #     hsv = cv2.cvtColor(self.img1, cv2.COLOR_RGB2HSV)  # RGB转换为hsv
    #     self.img1 = temp
    #     if not hasattr(self, 'img2'):  # 判断是否有img这个属性
    #         setattr(self, 'img2', '')
    #     self.img2 = hsv
    #     if not hasattr(self, 'imgtk2'):  # 判断是否有img这个属性
    #         setattr(self, 'imgtk2', '')  # 设置属性
    #     self.imgtk2 = self.photo_chage2()
    #     self.canvas2.create_image(0, 0, anchor="nw", image=self.imgtk2)
    # # RGB转换为BGR
    # def do_job1_5(self):
    #     temp = self.img1
    #     bgr = cv2.cvtColor(self.img1, cv2.COLOR_RGB2BGR)  # RGB转换为BGR
    #     self.img1 = temp
    #     if not hasattr(self, 'img2'):  # 判断是否有img这个属性
    #         setattr(self, 'img2', '')
    #     self.img2 = bgr
    #     if not hasattr(self, 'imgtk2'):  # 判断是否有img这个属性
    #         setattr(self, 'imgtk2', '')  # 设置属性
    #     self.imgtk2 = self.photo_chage2()
    #     self.canvas2.create_image(0, 0, anchor="nw", image=self.imgtk2)
    #保存img2的图片
    def do_job1_6(self):
        a = tkinter.filedialog.asksaveasfilename()  # 返回文件名
        if  hasattr(self, 'img2_Ima'):
            self.img2_Ima.save(a)
            tkinter.messagebox.showinfo('提示', '文件{}保存成功'.format(a))
        else:
            raise Exception
    #退出
    def do_job1_7(self):
        self.tk.quit()

    #第二个菜单接口--------------------------------------------------------
    def do_job2_1(self):
        pass
    #第三个菜单接口-------------------------------------------------------
    #移动
    def do_job3_1(self):
        li = self.value.split()
        M0 = np.float32([[1, 0, li[0]], [0, 1, li[1]]])
        dst0 = cv2.warpAffine(self.img1, M0, (self.cols, self.rows))
        self.Out_photo(dst0)
    #旋转
    def do_job3_2(self):
        angle = int(self.value)
        M1 = cv2.getRotationMatrix2D((self.cols / 2, self.rows / 2), angle, 1)
        # 第三个参数是输出图像的尺寸
        dst1 = cv2.warpAffine(self.img1, M1, (self.cols, self.rows))
        self.Out_photo(dst1)
    #垂直镜像
    def do_job3_3(self):
        M2 = np.float32([[1, 0, 0], [0, -1, self.cols]])
        dst2 = cv2.warpAffine(self.img1, M2, (self.cols, self.rows))
        self.Out_photo(dst2)
    #水平镜像
    def do_job3_4(self):
        M3 = np.float32([[-1, 0, self.cols], [0, 1, 0]])
        dst3 = cv2.warpAffine(self.img1, M3, (self.cols, self.rows))
        self.Out_photo(dst3)
    #缩放
    def do_job3_5(self):
        li = self.value.split()
        res = cv2.resize(self.img1, 0.5, fx=float(li[0]), fy=float(li[1]), interpolation=cv2.INTER_CUBIC)
        self.Out_photo(res)
    #仿射变换
    def do_job3_6(self):
        pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
        pts2 = np.float32([[10, 100], [200, 50], [100, 250]])
        M = cv2.getAffineTransform(pts1, pts2)
        dst = cv2.warpAffine(self.img1, M, (self.cols, self.rows))
        if not hasattr(self, 'img2'):   #判断是否有img这个属性
            setattr(self,'img2','')
        self.img2 = dst
        if not hasattr(self, 'imgtk2'):   #判断是否有img这个属性
            setattr(self, 'imgtk2','')   #设置属性
        self.imgtk2 = self.photo_chage_2()
        self.canvas2.create_image(0, 0, anchor="nw", image=self.imgtk2)
    #透视变换
    def do_job3_7(self):
        pts1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
        pts2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])
        M = cv2.getPerspectiveTransform(pts1, pts2)
        dst = cv2.warpPerspective(self.img1, M, (300, 300))
        if not hasattr(self, 'img2'):   #判断是否有img这个属性
            setattr(self,'img2','')
        self.img2 = dst
        if not hasattr(self, 'imgtk2'):   #判断是否有img这个属性
            setattr(self, 'imgtk2','')   #设置属性
        self.imgtk2 = self.photo_chage_2()
        self.canvas2.create_image(0, 0, anchor="nw", image=self.imgtk2)
    # 最近邻插值
    def do_job3_8(self):
        dstH, dstW = int(self.cols * 1.2),int(self.rows * 1.2)
        scrH, scrW= self.cols,self.rows
        retimg = np.zeros((dstH, dstW, 3), dtype=np.uint8)
        for i in range(dstH):
            for j in range(dstW):
                scrx = round((i + 1) * (scrH / dstH))
                scry = round((j + 1) * (scrW / dstW))
                retimg[i, j] = self.img1[scrx - 1, scry - 1]
        if not hasattr(self, 'img2'):  # 判断是否有img这个属性
            setattr(self, 'img2', '')
        self.img2 = retimg
        if not hasattr(self, 'imgtk2'):  # 判断是否有img这个属性
            setattr(self, 'imgtk2', '')  # 设置属性
        self.imgtk2 = self.photo_chage_2()
        self.canvas2.create_image(0, 0, anchor="nw", image=self.imgtk2)
    #双线性插值
    def do_job3_9(self):
        dstH, dstW = int(self.cols *1.2), int(self.rows *1.2)
        scrH, scrW = self.cols,self.rows
        img = np.pad(self.img1, ((0, 1), (0, 1)), 'constant')
        retimg = np.zeros((dstH, dstW, 3), dtype=np.uint8)
        for i in range(dstH):
            for j in range(dstW):
                scrx = (i + 1) * (scrH / dstH) - 1
                scry = (j + 1) * (scrW / dstW) - 1
                x = math.floor(scrx)
                y = math.floor(scry)
                u = scrx - x
                v = scry - y
                retimg[i, j] = (1 - u) * (1 - v) * img[x, y] + u * (1 - v) * img[x + 1, y] + (1 - u) * v * img[
                    x, y + 1] + u * v * img[x + 1, y + 1]
        if not hasattr(self, 'img2'):  # 判断是否有img这个属性
            setattr(self, 'img2', '')
        self.img2 = retimg
        if not hasattr(self, 'imgtk2'):  # 判断是否有img这个属性
            setattr(self, 'imgtk2', '')  # 设置属性
        self.imgtk2 = self.photo_chage_2()
        self.canvas2.create_image(0, 0, anchor="nw", image=self.imgtk2)
    # 三次内插法
    def do_job3_10(self):
        dstH, dstW = int(self.cols * 1.2), int(self.rows * 1.2)
        scrH, scrW = self.cols, self.rows
        retimg = np.zeros((dstH, dstW, 3), dtype=np.uint8)
        for i in range(dstH):
            for j in range(dstW):
                scrx = i * (scrH / dstH)
                scry = j * (scrW / dstW)
                x = math.floor(scrx)
                y = math.floor(scry)
                u = scrx - x
                v = scry - y
                tmp = 0
                for ii in range(-1, 2):
                    for jj in range(-1, 2):
                        if x + ii < 0 or y + jj < 0 or x + ii >= scrH or y + jj >= scrW:
                            continue
                        tmp += self.img1[x + ii, y + jj] * self.BiBubic(ii - u) * self.BiBubic(jj - v)
                retimg[i, j] = np.clip(tmp, 0, 255)
        if not hasattr(self, 'img2'):  # 判断是否有img这个属性
            setattr(self, 'img2', '')
        self.img2 = retimg
        if not hasattr(self, 'imgtk2'):  # 判断是否有img这个属性
            setattr(self, 'imgtk2', '')  # 设置属性
        self.imgtk2 = self.photo_chage_2()
        self.canvas2.create_image(0, 0, anchor="nw", image=self.imgtk2)

    # 第四个菜单接口-------------------------------------------------------------
    def do_job4_1(self):
        pass
    # 第五个菜单接口-------------------------------------------------------------
    #模板1
    def do_job5_1(self):
        ImgSmoothed1 = self.k1()
        if not hasattr(self, 'img3'):  # 判断是否有img这个属性
            setattr(self, 'img3', '')
        self.img3 = ImgSmoothed1
        self.imgtk1 = self.photo_chage_3()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
        self.SimpleRPMPrint(self.img2,self.img3)
    #模板2
    def d0_job5_2(self):
        ImgSmoothed1 = self.k2()
        if not hasattr(self, 'img3'):  # 判断是否有img这个属性
            setattr(self, 'img3', '')
        self.img3 = ImgSmoothed1
        self.imgtk1 = self.photo_chage_3()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
        self.SimpleRPMPrint(self.img1, self.img3)
    #模板3
    def do_job5_3(self):
        ImgSmoothed1 = self.k3()
        if not hasattr(self, 'img3'):  # 判断是否有img这个属性
            setattr(self, 'img3', '')
        self.img3 = ImgSmoothed1
        self.imgtk1 = self.photo_chage_3()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
        self.SimpleRPMPrint(self.img1, self.img3)
    #高斯滤波
    def do_job5_4(self):
        ImgSmoothed1 = self.k4()
        if not hasattr(self, 'img3'):  # 判断是否有img这个属性
            setattr(self, 'img3', '')
        self.img3 = ImgSmoothed1
        self.imgtk1 = self.photo_chage_3()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
        self.SimpleRPMPrint(self.img1, self.img3)
    # 中值波波
    def do_job5_5(self):
        ImgSmoothed1 = self.k5()
        if not hasattr(self, 'img3'):  # 判断是否有img这个属性
            setattr(self, 'img3', '')
        self.img3 = ImgSmoothed1
        self.imgtk1 = self.photo_chage_3()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
        self.SimpleRPMPrint(self.img1, self.img3)
    # 最大滤波
    def do_job5_6(self):
        ImgSmoothed1 = self.k6()
        if not hasattr(self, 'img3'):  # 判断是否有img这个属性
            setattr(self, 'img3', '')
        self.img3 = ImgSmoothed1
        self.imgtk1 = self.photo_chage_3()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
        self.SimpleRPMPrint(self.img1, self.img3)

    # 最小滤波
    def do_job5_7(self):
        ImgSmoothed1 = self.k7()
        if not hasattr(self, 'img3'):  # 判断是否有img这个属性
            setattr(self, 'img3', '')
        self.img3 = ImgSmoothed1
        self.imgtk1 = self.photo_chage_3()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
        self.SimpleRPMPrint(self.img1, self.img3)
    #Pad the image
    def do_job5_8(self):
        CONSTANT = self.kk1()
        self.Out_photo(CONSTANT)
        self.SimpleRPMPrint(self.img1, self.img2)
    # Replicate border pixels
    def do_job5_9(self):
        REPLICATE = self.kk2()
        self.Out_photo(REPLICATE)
        self.SimpleRPMPrint(self.img1, self.img2)
    # Mirror-reflecting at borders
    def do_job5_10(self):
        DEFAULT = self.kk3()
        self.Out_photo(DEFAULT)
        self.SimpleRPMPrint(self.img1, self.img2)
    # Allow pixels wrap around the image
    def do_job5_11(self):
        WRAP = self.kk4()
        self.Out_photo(WRAP)
        self.SimpleRPMPrint(self.img1, self.img2)
    #梯度锐化
    def do_job5_12(self):
        gradient1 = self.kkk1()
        self.Out_photo(gradient1)
    # sobel锐化
    def do_job5_13(self):
        Sobel = self.kkk2()
        self.Out_photo(Sobel)
    #LOG锐化
    def do_job5_14(self):
        LOG = self.kkk3()
        self.Out_photo(LOG)
    # 拉普拉斯锐化
    def do_job5_15(self):
        laplacian = self.kkk4()
        self.Out_photo(laplacian)
    #canny锐化
    def do_job5_16(self):
        canny = self.kkk5()
        self.Out_photo(canny)
    # 第六个菜单接口-------------------------------------------------------------
    #傅里叶正变换
    def do_job6_1(self):
        img = self.img1
        f = np.fft.fft2(img)
        fshift = np.fft.fftshift(f)
        magnitude_spectrum0 = 20 * np.log(1 + np.abs(fshift))
        self.Out_photo(magnitude_spectrum0)
     # 第七个菜单接口-------------------------------------------------------------
    def do_job7_1(self):
        NoiseImg = self.SaltAndPepper(self.img1,0.1)
        self.Out_photo(NoiseImg)
    # 第八个菜单接口-------------------------------------------------------------
    # 带通滤波 R通带半径 Cru通带粗细
    def do_job8_1(self):
        img = self.img1
        fshift = self.FFTCV2(img)
        if self.aquire_text():
            li = self.value.split()#R,Cru ,100,20
            handfft = self.handp(fshift, int(li[0]), int(li[1])) * fshift
        else:
            handfft = self.handp(fshift) * fshift
        magnitude_spectrum0 = 20 * np.log(1 + np.abs(handfft))
        img = self.IFFTcv2(handfft)
        self.Out_photo(img)
    #带阻滤波 R阻带半径 Cru阻带粗细
    def do_job8_2(self):
        img = self.img1
        fshift = self.FFTCV2(img)
        if self.aquire_text():
            li = self.value.split()  # R,Cru,100,20
            handstfft = self.handst(fshift, int(li[0]), int(li[1])) * fshift
        else:
            handstfft = self.handst(fshift) * fshift
        magnitude_spectrum0 = 20 * np.log(1 + np.abs(handstfft))
        img = self.IFFTcv2(handstfft)
        self.Out_photo(img)
    #添加条纹噪声
    def do_job8_3(self):
        img = self.img1
        fshift = self.FFTCV2(img)
        if self.aquire_text():
            li = self.value.split()  #条纹噪声方向大小距离direc,bulk,distanc ,90 5 20
            FFtimg = self.addNoise(fshift, int(li[0]),int(li[1]),int(li[2])) * fshift
        else:
            FFtimg = self.addNoise(fshift) * fshift
        # FFtimg1 = incNoise(FFtimg,90,5,20,1/100)*fshift
        # FFtimg2 = handst(FFtimg,20,5)*fshift
        img1 = self.IFFTcv2(FFtimg)
        self.Out_photo(img1)
    #陷波器
    def do_job8_4(self):
        img = self.img1
        fshift = self.FFTCV2(img)
        if self.aquire_text():
            li = self.value.split()  # 条纹噪声方向大小距离direc,bulk,distanc,陷波深度 90 5 20 0.01
            FFtimg = self.incNoise(fshift, int(li[0]), int(li[1]), int(li[2]),float(li[3])) * fshift
        else:
            FFtimg = self.incNoise(fshift) * fshift
        # FFtimg1 = incNoise(FFtimg,90,5,20,1/100)*fshift
        # FFtimg2 = handst(FFtimg,20,5)*fshift
        img1 = self.IFFTcv2(FFtimg)
        SNR = self.SignalNoiseRatio(self.img1,img1)
        self.text.delete(0, END)
        self.text.insert(0, ("信噪比:{}".format( SNR)))
        self.Out_photo(img1)
    # 第九个菜单接口-------------------------------------------------------------
    #高斯模糊
    def do_job9_1(self):
        image = self.img1
        PSF = self.Gauss_PSF(3,0.1)
        blurred = self.make_blurred(image, PSF)
        if not hasattr(self, 'PSF'):   #判断是否有PSF这个属性
            setattr(self,'PSF','')
        self.PSF = PSF
        self.Out_photo(blurred)
        self.SimpleRPMPrint(self.img1, self.img2)
    #运动模糊
    def do_job9_2(self):
        image = self.img1
        PSF = self.motion_PSF()
        blurred = self.make_blurred(image, PSF)
        if not hasattr(self, 'PSF'):   #判断是否有PSF这个属性
            setattr(self,'PSF','')
        self.PSF = PSF
        self.Out_photo(blurred)
        self.SimpleRPMPrint(self.img1, self.img2)
    #大气湍流模糊
    def do_job9_3(self):
        image = self.img1
        PSF = self.daqituanliu_PSF(image, 0.0025)
        blurred = self.make_blurred(image, PSF)
        if not hasattr(self, 'PSF'):   #判断是否有PSF这个属性
            setattr(self,'PSF','')
        self.PSF = PSF
        self.Out_photo(blurred)
        self.SimpleRPMPrint(self.img1, self.img2)

    #逆滤波
    def do_job9_4(self):
        result1 = self.inverse(self.img2, self.PSF)  # 逆滤波
        if not hasattr(self, 'img3'):  # 判断是否有img这个属性
            setattr(self, 'img3', '')
        self.img3 = result1
        self.SimpleRPMPrint(self.img1, result1)
        self.imgtk1 = self.photo_chage_3()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
    #改进逆滤波
    def do_job9_5(self):
        result2 = self.improving_inverse(self.img2, self.PSF, 30, 1)  # 改进逆滤波
        if not hasattr(self, 'img3'):  # 判断是否有img这个属性
            setattr(self, 'img3', '')
        self.img3 = result2
        self.SimpleRPMPrint(self.img1, result2)
        self.imgtk1 = self.photo_chage_3()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
    #维纳滤波
    def do_job9_6(self):
        K = self.caculateWiener(self.img1,self.img2,self.PSF)
        result3 = self.wiener(self.img2, self.PSF, K)  # 维纳滤波
        if not hasattr(self, 'img3'):  # 判断是否有img这个属性
            setattr(self, 'img3', '')
        self.img3 = result3
        self.SimpleRPMPrint(self.img1, result3)
        self.imgtk1 = self.photo_chage_3()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
    # 最小二乘滤波
    def do_job9_7(self):
        K2 = self.caculate_constrained_least_squares(self.img1,self.img2,self.PSF)
        result4 = self.constrained_least_squares(self.img2, self.PSF, K2)  # 最小二乘滤波
        if not hasattr(self, 'img3'):  # 判断是否有img这个属性
            setattr(self, 'img3', '')
        self.img3 = result4
        self.SimpleRPMPrint(self.img1, result4)
        self.imgtk1 = self.photo_chage_3()
        self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)

    # 第十个菜单接口-------------------------------------------------------------
    def do_job10_1(self):
        ret, binary = cv2.threshold(self.img1, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        se = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3), (-1, -1))
        dilate = cv2.dilate(binary, se, None, (-1, -1), 1)
        self.Out_photo(dilate)
    def do_job10_2(self):
        ret, binary = cv2.threshold(self.img1, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        se = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3), (-1, -1))
        erode = cv2.erode(binary, se, None, (-1, -1), 1)
        self.Out_photo(erode)
    def do_job10_3(self):
        ret, binary = cv2.threshold(self.img1, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        se = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3), (-1, -1))
        erode = cv2.erode(binary, se, None, (-1, -1), 1)
        boutain = binary - erode
        self.Out_photo(boutain)
    def do_job10_4(self):
        ret, binary = cv2.threshold(self.img1, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        se = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5), (-1, -1))
        binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, se)
        self.Out_photo(binary)
    def do_job10_5(self):
        ret, binary = cv2.threshold(self.img1, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        se1 = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 25), (-1, -1))
        binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, se1)
        self.Out_photo(binary)
    def do_job10_6(self):
        img = self.connected_components_demo(self.img1)
        self.Out_photo(img)
    # 第十一个菜单接口-------------------------------------------------------------
    def do_job11_1(self):
        pass
    # 第十二个菜单接口-------------------------------------------------------------
    def do_job12_1(self):
        th = self.Basic_Global_Thresholding()
        Img = self.Img_proessed(th)
        self.Out_photo(Img)
    #OTSU
    def do_job12_2(self):
        suitable_th = self.OTSU_enhance(self.img1,th_begin=0, th_end=256, th_step=1)
        th1 = self.OTSU_single(self.img1,suitable_th)
        self.Out_photo(th1)
    #subdivision
    def do_job12_3(self):
        Img = self.cut2(self.img1,2,3)
        self.Out_photo(Img)

    def get_attr(self):
        cols,rows = self.img1.shape
        if not hasattr(self, 'cols'):   #判断是否有img这个属性
            setattr(self,'img2','')
        self.cols = cols
        if not hasattr(self, 'rows'):   #判断是否有img这个属性
            setattr(self, 'imgtk2','')   #设置属性
        self.rows = rows
    #用于将原图Image显示于tk
    def photo_chage(self):#将图片转成Tkinter兼容的
        imgtk = ImageTk.PhotoImage(image=self.img1_Ima)
        return imgtk
    #用于将变换后的Image图片显示于tk
    def photo_chage_1(self):#将图片转成Tkinter兼容的
        imgtk = ImageTk.PhotoImage(image=self.img2_Ima)
        return imgtk
    #将变换后的灰度图片转为可以在tk显示的图片
    def photo_chage_2(self):
        img = Image.fromarray(self.img2)
        imgtk = ImageTk.PhotoImage(img)
        return imgtk
    #将滤波后的图转为可以在tk显示的图
    def photo_chage_3(self):
        img = Image.fromarray(self.img3)
        imgtk = ImageTk.PhotoImage(img)
        return imgtk

    # 将摄像头拍的图转为可以在tk显示的图
    def photo_chage_4(self):
        img = Image.fromarray(self.img1)
        imgtk = ImageTk.PhotoImage(img)
        return imgtk
    #摄像头处理
    def video_loop(self,cap):
        if cap.isOpened():
            while (True):
                susses,frame = cap.read()
                frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
                cv2.imshow('Image', frame)
                k = cv2.waitKey(100)
                if k == ord('a') or k == ord('A'):
                    cv2.imwrite('test.jpg', frame)
                    self.img1 = cv2.imread('test.jpg', 0)
                    self.img1 = cv2.resize(self.img1, (360, 350))
                    self.get_attr()
                    self.img1_Ima = Image.open('test.jpg').resize((360, 350))
                    # print(filename)
                    if not hasattr(self, 'imgtk1'):  # 判断是否有img这个属性
                        setattr(self, 'imgtk1', '')  # 设置属性
                    # self.get_attr()
                    self.imgtk1 = self.photo_chage()
                    self.canvas1.create_image(0, 0, anchor="nw", image=self.imgtk1)
                    break
                elif k ==ord('q') or k == ord('Q'):
                    break
        else:
            raise Exception
    #job3——10找最佳插值函数
    def BiBubic(self,x):
        x = abs(x)
        if x <= 1:
            return 1 - 2 * (x ** 2) + (x ** 3)
        elif x < 2:
            return 4 - 8 * x + 5 * (x ** 2) - (x ** 3)
        else:
            return 0

    # ----------------------------------------第五个菜单的函数模块放置处----------------------------------------
    def k1(self):
        fil1 = 1 / 16 * np.array([[1, 2, 1],  # 这个是设置的滤波核1
                                  [2, 4, 2],
                                  [1, 2, 1]])
        ImgSmoothed1 = cv2.filter2D(self.img2, -1, fil1, borderType=cv2.BORDER_DEFAULT)
        return ImgSmoothed1

    def k2(self):
        fil2 = 1 / 9 * np.array([[1, 1, 1],  # 这个是设置的滤波核2
                                 [1, 1, 1],
                                 [1, 1, 1]])
        ImgSmoothed1 = cv2.filter2D(self.img2, -1, fil2, borderType=cv2.BORDER_DEFAULT)
        return ImgSmoothed1

    def k3(self):
        fil3 = 1 / 10 * np.array([[1, 1, 1],  # 这个是设置的滤波核3
                                  [1, 2, 1],
                                  [1, 1, 1]])
        ImgSmoothed1 = cv2.filter2D(self.img2, -1, fil3, borderType=cv2.BORDER_DEFAULT)
        return ImgSmoothed1

    def k4(self):
        img_Guassian = cv2.GaussianBlur(self.img2, (5, 5), 0)
        return img_Guassian

    def k5(self):
        img_median = cv2.medianBlur(self.img2, 5)
        return img_median
    # 最大滤波函数
    def k6(self):
        img1 = self.img2
        rows = img1.shape[0]
        cols = img1.shape[1]
        for i in range(2, rows - 1):
            for j in range(2, cols - 1):
                for k in range(i - 1, i + 1):
                    for m in range(j - 1, j + 1):
                        if self.img2[i, j] < self.img2[k, m]:
                            img1[i, j] = self.img2[k, m]
        return img1
    # 最小滤波函数
    def k7(self):
        img1 = self.img2
        rows = img1.shape[0]
        cols = img1.shape[1]
        for i in range(2, rows - 1):
            for j in range(2, cols - 1):
                for k in range(i - 1, i + 1):
                    for m in range(j - 1, j + 1):
                        if self.img2[i, j] > self.img2[k, m]:
                            img1[i, j] = self.img2[k, m]
        return img1

    def kk1(self):
        CONSTANT = cv2.copyMakeBorder(self.img1, 10, 10, 10, 10, borderType=cv2.BORDER_CONSTANT)
        return CONSTANT

    def kk2(self):
        REPLICATE = cv2.copyMakeBorder(self.img1, 10, 10, 10, 10, borderType=cv2.BORDER_REPLICATE)
        return REPLICATE

    def kk3(self):
        DEFAULT = cv2.copyMakeBorder(self.img1, 10, 10, 10, 10, borderType=cv2.BORDER_DEFAULT)
        return DEFAULT

    def kk4(self):
        WRAP = cv2.copyMakeBorder(self.img1, 10, 10, 10, 10, borderType=cv2.BORDER_WRAP)
        return WRAP

    def kkk1(self):
        fil2 = 1 * np.array([[1, -1]])
        fil3 = 1 * np.array([[1],
                             [-1]])
        gradient1 = cv2.filter2D(self.img1, -1, fil2, borderType=cv2.BORDER_DEFAULT)
        gradient2 = cv2.filter2D(self.img1, -1, fil3, borderType=cv2.BORDER_DEFAULT)

        rows = gradient1.shape[0]
        cols = gradient1.shape[1]
        for i in range(rows):
            for j in range(cols):
                gradient1[i, j] = math.sqrt(pow(gradient1[i, j], 2) + pow(gradient2[i, j], 2))
        return gradient1

    def kkk2(self):
        x = cv2.Sobel(self.img1, cv2.CV_16S, 1, 0)
        y = cv2.Sobel(self.img1, cv2.CV_16S, 0, 1)
        absX = cv2.convertScaleAbs(x)
        absY = cv2.convertScaleAbs(y)
        Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
        return Sobel

    def kkk3(self):
        # 设置LOG的卷积核
        fil1 = 1 * np.array([[0, 0, 1, 0, 0],
                             [0, 1, 2, 1, 0],
                             [1, 2, -16, 2, 1],
                             [0, 1, 2, 1, 0],
                             [0, 0, 1, 0, 0]])
        LOG = cv2.filter2D(self.img1, -1, fil1, borderType=cv2.BORDER_DEFAULT)
        return LOG

    def kkk4(self):
        gray_lap = cv2.Laplacian(self.img1, cv2.CV_16S, ksize=3)
        laplacian = cv2.convertScaleAbs(gray_lap)
        return laplacian
    def kkk5(self):
        canny = cv2.Canny(self.img1, 50, 150)
        return canny
    # 给图像添加高斯噪声
    def addGaussianNoise(self,means, sigma):
        src = self.img1
        NoiseImg = src / src.max()
        rows = NoiseImg.shape[0]
        cols = NoiseImg.shape[1]
        for i in range(rows):
            for j in range(cols):
                # python里使用random.gauss函数加高斯噪声
                NoiseImg[i, j] = NoiseImg[i, j] + random.gauss(means, sigma)
                if NoiseImg[i, j] < 0:
                    NoiseImg[i, j] = 0
                elif NoiseImg[i, j] > 1:
                    NoiseImg[i, j] = 1
        return NoiseImg

    # ----------------------------------------第七个菜单的函数模块放置处----------------------------------------
    #椒盐噪声
    def SaltAndPepper(self,src, percetage):
        NoiseImg = src
        NoiseNum = int(percetage * src.shape[0] * src.shape[1])
        for i in range(NoiseNum):
            randX = random.randint(0, src.shape[0] - 1)
            randY = random.randint(0, src.shape[1] - 1)
            if random.randint(0, 1) == 0:
                NoiseImg[randX, randY] = 0
            else:
                NoiseImg[randX, randY] = 255
        return NoiseImg

    # ----------------------------------------第八个菜单的函数模块放置处----------------------------------------
    def FFTCV2(self,img):
        f = np.fft.fft2(img)
        fshift = np.fft.fftshift(f)
        magnitude_spectrum0 = 20 * np.log(1 + np.abs(fshift))
        # plt.subplot(111), plt.imshow(magnitude_spectrum0, cmap='gray')  # 显示移中后的幅值谱
        # plt.title('magnitude_spectrum after shift'), plt.xticks([]), plt.yticks([])
        return fshift
    def IFFTcv2(self,src):
        f1 = np.fft.ifftshift(src)
        img1 = abs(np.fft.ifft2(f1))  # 重构图像
        # cv2.imshow('重构的图像', img1)
        # plt.subplot(111), plt.imshow(img1, cmap='gray')  # 显示加噪图像
        # plt.title('Noisy Image'), plt.xticks([]), plt.yticks([])
        return img1
    # 比较信噪比
    def SNR2(self,img1, img2):
        Row, Col = img1.shape
        img1 = img1 - img2
        img1 = img1.sum()
        img1 = img1 / (Row * Col)
        snr = 10 * math.log((255.0 * 255.0 / (img1)), 10)
        return snr
    # 高通  大小
    def highp(self,src, bulk):
        Row, Col = src.shape
        mask = np.ones(src.shape, np.uint8)
        Rows1 = int(Row / 2)
        Cols1 = int(Col / 2)
        for k in range(Rows1 - bulk, Rows1 + bulk):
            y = k - Rows1
            y = math.sqrt(bulk * bulk - y * y)
            y = int(y.real)
            mask[k, Cols1 - y: Cols1 + y + 1] = 0
        return mask

    # 低通  大小
    def lowp(self,src, bulk):
        Row, Col = src.shape
        mask = np.zeros(src.shape, np.uint8)
        Rows1 = int(Row / 2)
        Cols1 = int(Col / 2)
        for k in range(Rows1 - bulk, Rows1 + bulk):
            y = k - Rows1
            y = math.sqrt(bulk * bulk - y * y)
            y = int(y.real)
            mask[k, Cols1 - y: Cols1 + y + 1] = 1
        return mask

    # 带通  R, 粗细
    def handp(self,src, R = 100, Cru = 20):
        mask = self.lowp(src, R + Cru)
        mask = self.highp(mask, R)
        return mask

    # 带阻  R, 粗细
    def handst(self,src, R = 100, Cru = 20):
        mask = self.lowp(src, R)
        mask1 = self.highp(src, R + Cru)
        mask = mask + mask1
        return mask

    # 定义函数，巴特沃斯带阻/通滤波模板
    def ButterworthBand(self,src, w, d0, n, ftype):
        template = np.zeros(src.shape, dtype=np.float32)  # 构建滤波器
        r, c = src.shape
        for i in np.arange(r):
            for j in np.arange(c):
                distance = np.sqrt((i - r / 2) ** 2 + (j - c / 2) ** 2)
                template[i, j] = 1 / (1 + (distance * w / (distance ** 2 - d0 ** 2)) ** (2 * n))
        if ftype == 'pass':
            template = 1 - template
        return template

    # 定义函数，高斯带阻/通滤波模板
    def GaussianBand(self,src, w, d0, ftype):
        template = np.zeros(src.shape, dtype=np.float32)  # 构建滤波器
        r, c = src.shape
        for i in np.arange(r):
            for j in np.arange(c):
                distance = np.sqrt((i - r / 2) ** 2 + (j - c / 2) ** 2)
                temp = ((distance ** 2 - d0 ** 2) / (distance * w + 0.00000001)) ** 2
                template[i, j] = 1 - np.exp(-0.5 * temp)
        if ftype == 'pass':
            template = 1 - template
        return template

    # 条纹噪声方向大小距离
    def addNoise(self,src, direc = 90, bulk = 5, distanc = 20):
        Row, Col = src.shape
        mask = np.ones(src.shape, np.uint8)
        Rows1 = Row / 2 + distanc * math.sin(direc / 360 * 2 * math.pi)
        Rows1 = int(Rows1.real)
        Cols1 = Col / 2 + distanc * math.cos(direc / 360 * 2 * math.pi)
        Cols1 = int(Cols1.real)
        for k in range(Rows1 - bulk, Rows1 + bulk):
            y = k - Rows1
            y = math.sqrt(bulk * bulk - y * y)
            y = int(y.real)
            mask[k, Cols1 - y: Cols1 + y + 1] = 10000

        # mask[Rows1-bulk: Rows1 + bulk, Cols1-bulk: Cols1+bulk] = 1000

        Rows1 = Row / 2 + distanc * math.sin((direc + 180) / 360 * 2 * math.pi)
        Rows1 = int(Rows1.real)
        Cols1 = Col / 2 + distanc * math.cos((direc + 180) / 360 * 2 * math.pi)
        Cols1 = int(Cols1.real)
        for k in range(Rows1 - bulk, Rows1 + bulk):
            y = k - Rows1
            y = math.sqrt(bulk * bulk - y * y)
            y = int(y.real)
            mask[k, Cols1 - y: Cols1 + y + 1] = 10000
        return mask

    # 陷波器方向大小距离,深度
    def incNoise(self,src, direc = 90, bulk = 5, distanc = 20 , desk = 0.01):
        Row, Col = src.shape
        mask = np.ones(src.shape, np.uint8)
        Rows1 = Row / 2 + distanc * math.sin(direc / 360 * 2 * math.pi)
        Rows1 = int(Rows1.real)
        Cols1 = Col / 2 + distanc * math.cos(direc / 360 * 2 * math.pi)
        Cols1 = int(Cols1.real)
        for k in range(Rows1 - bulk, Rows1 + bulk):
            y = k - Rows1
            y = math.sqrt(bulk * bulk - y * y)
            y = int(y.real)
            mask[k, Cols1 - y: Cols1 + y + 1] = desk

        # mask[Rows1-bulk: Rows1 + bulk, Cols1-bulk: Cols1+bulk] = 1000

        Rows1 = Row / 2 + distanc * math.sin((direc + 180) / 360 * 2 * math.pi)
        Rows1 = int(Rows1.real)
        Cols1 = Col / 2 + distanc * math.cos((direc + 180) / 360 * 2 * math.pi)
        Cols1 = int(Cols1.real)
        for k in range(Rows1 - bulk, Rows1 + bulk):
            y = k - Rows1
            y = math.sqrt(bulk * bulk - y * y)
            y = int(y.real)
            mask[k, Cols1 - y: Cols1 + y + 1] = desk
        return mask

    #----------------------------------------第九个菜单的函数模块放置处----------------------------------------
    def inverse(self,input, PSF, eps=0.001):  # 逆滤波
        PSF = self.extension_PSF(input, PSF)
        input_fft = fft.fft2(input)
        PSF_fft = fft.fft2(PSF) + eps
        Output_fft = input_fft / PSF_fft  # 在频域进行逆滤波
        result = fft.ifft2(Output_fft)  # 计算F(u,v)的傅里叶反变换
        result = np.abs(result)
        return result

    def wiener(self,input, PSF, K, eps=0.001):  # 维纳滤波
        PSF = self.extension_PSF(input, PSF)
        input_fft = fft.fft2(input)
        PSF_fft = fft.fft2(PSF) + eps
        PSF_fft = np.conj(PSF_fft) / (np.abs(PSF_fft) ** 2 + K)
        result = fft.ifft2(input_fft * PSF_fft)
        result = np.abs(result)
        return result

    def constrained_least_squares(self,input, PSF, z, eps=0.001):  # 最小二乘滤波
        PSF = self.extension_PSF(input, PSF)
        input_fft = fft.fft2(input)
        PSF_fft = fft.fft2(PSF) + eps
        laplace = np.array([[0, -1, 0],
                            [-1, 4, -1],
                            [0, -1, 0]])
        laplace = self.extension_PSF(input, laplace)
        laplace_fft = fft.fft2(laplace)
        PSF_fft = np.conj(PSF_fft) / (np.abs(PSF_fft) ** 2 + z * np.abs(laplace_fft) ** 2)
        result = fft.ifft2(input_fft * PSF_fft)
        result = np.abs(result)
        return result

    def improving_inverse(self,input, PSF, w, k, eps=0.001):  # 改进的逆滤波
        PSF = self.extension_PSF(input, PSF)
        input_fft = fft.fft2(input)
        PSF_fft = fft.fft2(PSF) + eps
        rows = input_fft.shape[0]
        cols = input_fft.shape[1]
        for u in range(rows):
            for v in range(cols):
                if u * u + v * v < w * w:
                    PSF_fft[u, v] = 1 / PSF_fft[u, v]
                else:
                    PSF_fft[u, v] = k
        Output_fft = input_fft * PSF_fft  # 在频域进行逆滤波
        result = fft.ifft2(Output_fft)  # 计算F(u,v)的傅里叶反变换
        result = np.abs(result)
        return result

    # 计算维纳滤波的最佳参数
    def caculateWiener(self,image, blurred, PSF):
        x = np.arange(0.001, 0.01, 0.001)
        length = len(x)
        y = np.zeros(length)
        for i in range(length):
            result = self.wiener(blurred, PSF, x[i])
            y[i] = self.meanSquare(image, result)
        minIndex = np.argmin(y)
        minX = x[minIndex]
        minX = round(minX, 4)
        return minX

    # 计算最小二乘滤波的最佳参数
    def caculate_constrained_least_squares(self,image, blurred, PSF):
        x = np.arange(0.001, 0.01, 0.001)
        length = len(x)
        y = np.zeros(length)
        for i in range(length):
            result = self.constrained_least_squares(blurred, PSF, x[i])
            y[i] = self.meanSquare(image, result)
        minIndex = np.argmin(y)
        minX = x[minIndex]
        minX = round(minX, 4)
        return minX

    def motion_PSF(self,kernel_size=15, angle=60):  # 此函数生成的运动模糊核是由旋转来控制运动方向
        PSF = np.diag(np.ones(kernel_size))  # 初始模糊核的方向是-45度
        angle = angle + 45  # 抵消-45度的影响
        M = cv2.getRotationMatrix2D((kernel_size / 2, kernel_size / 2), angle, 1)  # 生成旋转矩阵
        PSF = cv2.warpAffine(PSF, M, (kernel_size, kernel_size), flags=cv2.INTER_NEAREST)
        PSF = PSF / PSF.sum()  # 模糊核的权重和为1
        return PSF

    def Gauss_PSF(self,kernel_size, sigma):  # 生成高斯模糊核
        kx = cv2.getGaussianKernel(kernel_size, sigma)
        ky = cv2.getGaussianKernel(kernel_size, sigma)
        return np.multiply(kx, np.transpose(ky))

    def daqituanliu_PSF(self,input, k):  # 生成大气湍流模糊核
        [m, n] = input.shape
        PSF = np.zeros((m, n))
        p = m / 2
        q = n / 2
        for u in range(m):
            for v in range(n):
                PSF[u, v] = math.exp(-k * ((u - p) ** 2 + (v - q) ** 2) ** (5 / 6))

        PSF1 = fft.ifft2(PSF)
        PSF1 = np.abs(PSF1)
        PSF1 = PSF1 / PSF1.sum()  # 模糊核的权重和为1
        return PSF1

    def extension_PSF(self,image0, PSF0):  # 此函数扩展PSF0，使之与image0一样大小
        [img_h, img_w] = image0.shape
        [h, w] = PSF0.shape
        PSF = np.zeros((img_h, img_w))
        PSF[0:h, 0:w] = PSF0[0:h, 0:w]
        return PSF

    def make_blurred(self,input, PSF, eps=0.001):  # 在频域对图片进行模糊加噪
        PSF = self.extension_PSF(input, PSF)
        input_fft = fft.fft2(input)  # 进行二维数组的傅里叶变换
        PSF_fft = fft.fft2(PSF) + eps
        blurred = fft.ifft2(input_fft * PSF_fft)
        blurred = np.abs(blurred)
        blurred = blurred + 0.1 * blurred.std() * np.random.standard_normal(blurred.shape)
        return blurred

    def standardization(self,img, L=255):  # 将0-255范围的图像转化为0-1，将彩色图像转换为灰度图像
        if len(img.shape) > 2:  # 判断img.shape元组的长度
            if img.shape[2] != 1:
                img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        img = img / L
        return img

    def meanSquare(self,image0, image1, L=255):  # 求均方误差
        image0 = self.standardization(image0)
        image1 = self.standardization(image1)
        [m, n] = image0.shape
        MSE = 0
        for i in range(m):
            for j in range(n):
                MSE = MSE + (image0[i, j] - image1[i, j]) ** 2
        MSE = MSE / (m * n) * (L ** 2)
        return MSE

    def SignalNoiseRatio(self,image0, image1):  # 求信噪比，输出单位：dB
        image0 = self.standardization(image0)
        image1 = self.standardization(image1)
        [m, n] = image0.shape
        Np = 0
        Sp = 0
        for i in range(m):
            for j in range(n):
                Np = Np + (image0[i, j] - image1[i, j]) ** 2
                Sp = Sp + image1[i, j] ** 2
        SNR = 10 * math.log(Sp / (Np + 1e-14), 10)  # 防止除数为0
        return SNR

    def PeakSignalNoiseRatio(self,image0, image1, L=255):  # 求峰值信噪比，输出单位：dB
        MSE = self.meanSquare(image0, image1)
        PSNR = 10 * math.log(L ** 2 / (MSE + 1e-14), 10)  # 防止除数为0
        return PSNR

    def SimpleRPMPrint(self,image0, image1):  # 输出均方误差，信噪比，峰值信噪比
        MSE = int(self.meanSquare(image0, image1))
        SNR = int(self.SignalNoiseRatio(image0, image1))
        PSNR = int(self.PeakSignalNoiseRatio(image0, image1))
        self.text.delete(0,END)
        self.text.insert(0,("均方误差:{},信噪比:{},峰值信噪比:{}".format(MSE,SNR,PSNR)))

    # ----------------------------------------第九个菜单的函数模块放置处----------------------------------------
    # 连通分量提取
    def connected_components_demo(self,src):
        gray = src
        gray = cv2.GaussianBlur(gray, (3, 3), 0)
        ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        output = cv2.connectedComponents(binary, connectivity=8, ltype=cv2.CV_32S)
        num_labels = output[0]
        labels = output[1]
        colors = []
        for i in range(num_labels):
            b = np.random.randint(0, 256)
            g = np.random.randint(0, 256)
            r = np.random.randint(0, 256)
            colors.append((b, g, r))
        colors[0] = (0, 0, 0)
        h, w = gray.shape
        image = np.zeros((h, w, 3), dtype=np.uint8)
        for row in range(h):
            for col in range(w):
                image[row, col] = colors[labels[row, col]]
        return image
    # ----------------------------------------第十二个菜单的函数模块放置处----------------------------------------
    #迭代法获取阈值
    def Basic_Global_Thresholding(self):  # 输入的图像要求为灰度图像
        Img = self.img1
        T0 = 10  # 设置的最小的差值，也是迭代终止条件
        rows = Img.shape[0]
        cols = Img.shape[1]
        G1 = np.zeros(Img.shape, np.uint8)  # 定义矩阵分别用来装被阈值T1分开的两部分
        G2 = np.zeros(Img.shape, np.uint8)
        for i in range(rows):
            for j in range(cols):
                T1 = np.mean(Img)  # 设置初始阈值T1为图像灰度均值
                if Img[i, j] < T1:
                    G1[i, j] = Img[i, j]
                elif Img[i, j] >= T1:
                    G2[i, j] = Img[i, j]  # 用T1将图像分割成G1和G2两部分

                ave1 = np.mean(G1)
                ave2 = np.mean(G2)
                T2 = (ave1 + ave2) / 2
                if abs(T2 - T1) < T0:
                    break  # 当|T2-T1|<T0时，T2就是最合适的阈值
        return T2

    def Img_proessed(self, th):
        # src = img / img.max()
        img = self.img1
        rows = img.shape[0]
        cols = img.shape[1]
        for i in range(rows):
            for j in range(cols):
                if img[i, j] < th:
                    img[i, j] = 0
                if img[i, j] >= th:
                    img[i, j] = 255
        return img
    #大津法获取阈值
    def OTSU_enhance(self,img_gray1, th_begin=0, th_end=256, th_step=1):
        img_gray = img_gray1
        assert img_gray.ndim == 2, "must input a gary_img"
        max_g = 0
        suitable_th = 0
        for threshold in range(th_begin, th_end, th_step):  # th_begin表示起始像素点灰度值，即最小灰度值，一般为0
            bin_img = img_gray > threshold  # th_end表示结束像素点灰度值，即最大灰度值，一般取255
            bin_img_inv = img_gray <= threshold
            fore_pix = np.sum(bin_img)  # 前景像素点
            back_pix = np.sum(bin_img_inv)  # 背景像素点
            if 0 == fore_pix:
                break
            if 0 == back_pix:
                continue
            # size表示图像总像素个数
            w0 = float(fore_pix) / img_gray.size  # w0表示前景像素点占整幅图像大小的比例
            u0 = float(np.sum(img_gray * bin_img)) / fore_pix  # u0前景像素点的平均值
            w1 = float(back_pix) / img_gray.size  # w1表示背景像素点占整幅图像大小的比例
            u1 = float(np.sum(img_gray * bin_img_inv)) / back_pix  # u1表示背景像素点的平均值
            # intra-class variance
            g = w0 * w1 * (u0 - u1) * (u0 - u1)  # g为类间方差
            if g > max_g:
                max_g = g
                suitable_th = threshold
        return suitable_th  # 当g最大时，得到的阈值就是最合适的阈值
    #局部图像的可变阈值
    def division(self, m, n):
        src = self.img1
        a = src.max()
        rows = src.shape[0]
        cols = src.shape[1]
        m1 = int(rows / m)
        n1 = int(cols / n)
        img = src
        for i in range(0, m):
            for j in range(0, n):
                G = src[i * m1:(i + 1) * m1, j * n1:(j + 1) * n1]
                th = self.OTSU_enhance(G, th_begin=0, th_end=256, th_step=1)
                G = self.OTSU_single(G, th)
                img[i * m1:(i + 1) * m1, j * n1:(j + 1) * n1] = G * 255
        return img

    def cut2(self,src, m, n):
        a = src.max()
        rows = src.shape[0]
        cols = src.shape[1]
        m1 = int(rows / m)
        n1 = int(cols / n)
        print(m1, n1, rows, cols)

        img = src
        for i in range(0, m - 1):
            for j in range(0, n - 1):
                img[(i + 1) * m1, :] = 255
                img[:, (j + 1) * n1] = 255
        return img

    def OTSU_single(self, img1,th):
        img = img1
        # src = img / img.max()
        rows = img.shape[0]
        cols = img.shape[1]
        for i in range(rows):
            for j in range(cols):
                if img[i, j] < th:
                    img[i, j] = 0
                else:
                    img[i, j] = 255
        return img



if __name__ == '__main__':
    mygui = MyGUI()
    mygui()  #调用call函数

